package com.army.cookbook.slice;

import com.army.cookbook.ResourceTable;
import com.army.cookbook.util.LogUtils;
import com.army.cookbook.util.PermissionBridge;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.device.FrameConfig;

public class OpenCameraSlice extends AbilitySlice implements PermissionBridge.OnPermissionStateListener{
    private static final String TAG = OpenCameraSlice.class.getName();

    private static final int SCREEN_WIDTH = 1080;

    private static final int SCREEN_HEIGHT = 1920;

    private static final int SLEEP_TIME = 200;

    private EventHandler creamEventHandler;

    private Image exitImage;

    private SurfaceProvider surfaceProvider;

    private Image switchCameraImage;

    private boolean isCameraRear;

    private Camera cameraDevice;

    private Surface previewSurface;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_open_camera);
        new PermissionBridge().setOnPermissionStateListener(this);
    }

    private void initSurface() {
        surfaceProvider = new SurfaceProvider(this);
        DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
                ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
        surfaceProvider.setLayoutConfig(params);
        surfaceProvider.pinToZTop(false);
        // 添加SurfaceCallBack回调
        surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
        // 将SurfaceProvider加入到布局中
        Component component = findComponentById(ResourceTable.Id_surface_container);
        if (component instanceof ComponentContainer) {
            ((ComponentContainer) component).addComponent(surfaceProvider);
        }
    }

    private void initControlComponents() {
        // 退出拍照页面图标
        Component exitImageCom = findComponentById(ResourceTable.Id_exit);
        if (exitImageCom instanceof Image) {
            exitImage = (Image) exitImageCom;
            exitImage.setClickedListener(component -> terminate());
        }
        // 切换前后置摄像头图标
        Component switchCameraImageCom = findComponentById(ResourceTable.Id_switch_camera_btn);
        if (switchCameraImageCom instanceof Image) {
            switchCameraImage = (Image) switchCameraImageCom;
            switchCameraImage.setClickedListener(component -> switchClicked());
        }
    }

    private void switchClicked() {
        isCameraRear = !isCameraRear;
        openCamera();
    }

    private void openCamera() {
        CameraKit cameraKit = CameraKit.getInstance(getApplicationContext());
        String[] cameraLists = cameraKit.getCameraIds();
        String cameraId = cameraLists.length > 1 && isCameraRear ? cameraLists[1] : cameraLists[0];
        CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
        cameraKit.createCamera(cameraId, cameraStateCallback, creamEventHandler);
    }

    private void showTips(Context context, String message) {
        getUITaskDispatcher().asyncDispatch(() -> {
            ToastDialog toastDialog = new ToastDialog(context);
            toastDialog.setAutoClosable(false);
            toastDialog.setContentText(message);
            toastDialog.show();
        });
    }

    @Override
    public void onPermissionGranted() {
        getWindow().setTransparent(true);
        initSurface();
        initControlComponents();
        creamEventHandler = new EventHandler(EventRunner.create("======CameraBackground"));
    }

    @Override
    public void onPermissionDenied() {
        showTips(OpenCameraSlice.this, "=======No permission");
    }

    /**
     * CameraStateCallbackImpl
     */
    class CameraStateCallbackImpl extends CameraStateCallback {
        CameraStateCallbackImpl() {
        }

        @Override
        public void onCreated(Camera camera) {
            // 获取预览
            previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
            if (previewSurface == null) {
                LogUtils.error(TAG, "create camera filed, preview surface is null");
                return;
            }
            // Wait until the preview surface is created.
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException exception) {
                LogUtils.warn(TAG, "Waiting to be interrupted");
            }
            CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();
            // 配置预览
            cameraConfigBuilder.addSurface(previewSurface);
            camera.configure(cameraConfigBuilder.build());
            cameraDevice = camera;
            enableImageGroup();
        }

        @Override
        public void onConfigured(Camera camera) {
            FrameConfig.Builder framePreviewConfigBuilder
                    = camera.getFrameConfigBuilder(Camera.FrameConfigType.FRAME_CONFIG_PREVIEW);
            framePreviewConfigBuilder.addSurface(previewSurface);
            // 开启循环捕捉
            camera.triggerLoopingCapture(framePreviewConfigBuilder.build());
        }

        private void enableImageGroup() {
            if (!exitImage.isEnabled()) {
                exitImage.setEnabled(true);
                switchCameraImage.setEnabled(true);
            }
        }
    }

    /**
     * SurfaceCallBack
     */
    class SurfaceCallBack implements SurfaceOps.Callback {
        @Override
        public void surfaceCreated(SurfaceOps callbackSurfaceOps) {
            if (callbackSurfaceOps != null) {
                callbackSurfaceOps.setFixedSize(SCREEN_HEIGHT, SCREEN_WIDTH);
            }
            openCamera();
        }

        @Override
        public void surfaceChanged(SurfaceOps callbackSurfaceOps, int format, int width, int height) {
        }

        @Override
        public void surfaceDestroyed(SurfaceOps callbackSurfaceOps) {
        }
    }

    @Override
    public void onStop() {
        cameraDevice.release();
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}
